#include <stdint.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "module.h"
#include <stdint.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <sys/select.h>
#include "autoconfig.h"
#include "sys/err.h"

sys_api_t * sysapi;

int asc2bcd(char * ascstr, int len, uint8_t *bcdstr, int align)
{
        return sysapi->asc2bcd(ascstr, len, bcdstr, align);
}
int bcd2asc(uint8_t * bcd, int asclen, char * asc, int align)
{
        return sysapi->bcd2asc(bcd, asclen, asc, align);
}
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
        return sysapi->gettimeofday(tv, tz);
}
int settimeofday(const struct timeval *tv , const struct timezone *tz)
{
        return sysapi->settimeofday(tv, tz);
}

int open(const char *pathname, int oflag, ... /* mode_t mode */)
{
        return sysapi->open(pathname, oflag);
}

int close(int fd)
{
        return sysapi->close(fd);
}

ssize_t read(int fd, void * buffer, size_t len)
{
        return sysapi->read(fd, buffer, len);
}

ssize_t write(int fd, const void * buffer, size_t len)
{
        return sysapi->write(fd, buffer, len);
}

int select(int nfds, fd_set *readfds, fd_set *writefds,
                   fd_set *exceptfds, struct timeval *timeout)
{
        return sysapi->select(nfds, readfds, writefds,
                        exceptfds, timeout);
}
int unlink(const char * pathname)
{
        return sysapi->unlink(pathname);
}

int ioctl(int fd, int cmd, void *arg)
{
	    return sysapi->ioctl(fd, cmd, arg);
}

off_t lseek(int fd, off_t offset, int whence)
{
        return sysapi->lseek(fd, offset, whence);
}

int truncate(int fd, off_t lenght)
{
	    return sysapi->truncate(fd, lenght);
}

void lcd_backlight(uint32_t on)
{
    sysapi->lcd_backlight(on);
}

int lcd_set_attribute(uint8_t atr, void * arg)
{
	    return sysapi->lcd_set_attribute(atr, arg);
}

void lcd_clrscr(void)
{
        sysapi->lcd_clrscr();
}

int lcd_disp_img(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t * img)
{
        return sysapi->lcd_disp_img(x, y, w, h, img);
}

int lcd_disp_string(uint32_t x, uint32_t y, char * string)
{
        return sysapi->lcd_disp_string(x, y, string);
}

int lcd_disp_hline(uint32_t x, uint32_t y, uint32_t w)
{
        return sysapi->lcd_disp_hline(x, y, w);
}
int lcd_disp_vline(uint32_t x, uint32_t y, uint32_t h)
{
        return sysapi->lcd_disp_vline(x, y, h);
}

int lcd_get_type(void)
{
	    return sysapi->lcd_get_type();
}

int lcd_push(void)
{
	    return sysapi->lcd_push();
}

int lcd_pop(void)
{
	    return sysapi->lcd_pop();
}

int lcd_clrscr_line(uint32_t start_y, uint32_t end_y)
{
	    return sysapi->lcd_clrscr_line(start_y, end_y);
}

int lcd_goto_xy(uint32_t x, uint32_t y)
{
	    return sysapi->lcd_goto_xy(x, y);
}

int lcd_get_xy(uint32_t *px, uint32_t *py)
{
	    return sysapi->lcd_get_xy(px, py);
}

int lcd_set_view_port(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
	    return sysapi->lcd_set_view_port(x, y, w, h);
}

int lcd_get_view_port(uint32_t *px, uint32_t *py, uint32_t *pw, uint32_t *ph)
{
	    return sysapi->lcd_get_view_port(px, py, pw, ph);
}

int lcd_printf(const char *fmt, ...)
{
    int ret;
    
    va_list args;
    
    va_start(args,fmt);
    ret = _doprntx(fmt, args, sysapi->lcd_putch, 0);
    va_end(args);

    return ret; 
}

int lcd_set_font(lcd_font_type_em emtype)
{
	    return sysapi->lcd_set_font(emtype);
}

int lcd_set_space(uint32_t wspace, uint32_t hspace)
{
	    return sysapi->lcd_set_space(wspace, hspace);
}

int lcd_get_size(uint32_t * pwidth, uint32_t * pheight)
{
	    return sysapi->lcd_get_size(pwidth, pheight);
}

int lcd_set_contrast(uint32_t contrast)
{
	    return sysapi->lcd_set_contrast(contrast);
}

int lcd_statusbar(lcd_statusbar_em  new_flag, lcd_statusbar_em  *pold_flag)
{
        return sysapi->lcd_statusbar(new_flag, pold_flag);
}

int kb_get_key(int ms)
{
        return sysapi->kb_get_key(ms);
}


int kb_get_str(char * input, int in_len, 
                    int min_len, int max_len, 
                    int timeout, char show, int mode)
{
    return sysapi->kb_get_str(input, in_len, min_len, 
                                max_len, timeout, show, mode);
}

int kb_get_amount(char * amount, int max_len, int timeout)
{
    return sysapi->kb_get_amount(amount, max_len, timeout);
}

int serial_init(uint32_t id, serial_info_t * info)
{
        return sysapi->serial_init(id, info);
}
int serial_write(uint32_t id, uint8_t * buffer, size_t len)
{
        return sysapi->serial_write(id, buffer, len);
}

int serial_read(uint32_t id, uint8_t * buffer, size_t len, int timeout)
{
        return sysapi->serial_read(id, buffer, len, timeout);
}

int serial_clrbuf(uint32_t id, int rx, int tx)
{
        return sysapi->serial_clrbuf(id, rx, tx);
}


int icc_status( uint8_t *status, int *status_len )
{
        return sysapi->icc_status(status, status_len);
}

int icc_power_up( int cardno, uint8_t *out, int *outlen )
{
		return sysapi->icc_power_up(cardno, out, outlen);
}

int icc_send_apdu( int cardno, uint8_t* in, int inlen, uint8_t *out, int *outlen )
{
		return sysapi->icc_send_apdu(cardno, in, inlen, out, outlen);
}

int icc_power_down( int cardno )
{
		return sysapi->icc_power_down( cardno );
}

int pos_entry(pos_entry_t entry, pos_entry_un *data, int ms)
{
        return sysapi->pos_entry(entry, data, ms);
}

void reset(void)
{
        sysapi->reset();
}

void mdelay(uint32_t ms)
{
        sysapi->mdelay(ms);
}

void buzzer_start(void)
{
        sysapi->buzzer_start();
}

void buzzer_stop(void)
{
        sysapi->buzzer_stop();
}

void led_ctrl(uint32_t nr, uint32_t on)
{
        sysapi->led_ctrl(nr, on); 
}

uint32_t security_status(void)
{
        return sysapi->security_status();
}

int nv_write(uint32_t offset, uint8_t * buf, int buflen)
{
        return sysapi->nv_write(offset, buf, buflen);
}

int nv_read(uint32_t offset, uint8_t * buf, int buflen)
{
        return sysapi->nv_read(offset, buf, buflen);
}

int sys_get_param(uint32_t type, void *buf, uint32_t len)
{
	    return sysapi->sys_get_param(type, buf, len);
}

int sys_set_param(uint32_t type, void *buf, uint32_t len)
{
	    return sysapi->sys_set_param(type, buf, len);
}

void * sys_load_library(char *name)
{
        return sysapi->sys_load_library(name);
}

int sys_run_app(char *name)
{
        return sysapi->sys_run_app(name);
}

int sys_update_mod(mod_update_t *update, uint8_t nr)
{
        return sysapi->sys_update_mod(update, nr);
}

uint32_t timeout_start(void)
{
	    return sysapi->timeout_start();
}

uint32_t timeout_test(uint32_t *start, uint32_t *ms)
{
	    return sysapi->timeout_test(start, ms);
}


int sys_cpufreq_notify_transition(unsigned long freq,  void *data)
{
        return sysapi->sys_cpufreq_notify_transition(freq, data);
}

int sys_sleep(int sleep, void *flush_func, int flush_time)
{
        return sysapi->sys_sleep(sleep, flush_func, flush_time);
}

int sys_pm_ctrl(int onoff)
{
    return sysapi->sys_pm_ctrl(onoff);
}

int sys_read_battery_status(uint32_t *voltage, uint8_t *level, 
                        uint32_t *button_vol)
{
        return sysapi->sys_read_battery_status(voltage, level, button_vol);
}

int voice_file_play(char * pszFile)
{
    return sysapi->voice_file_play(pszFile);
}

int voice_ctrl_volume(uint32_t vol)
{
    return sysapi->voice_ctrl_volume(vol);
}

int default_fn(void){return 0;}
int appmod_init(void) __attribute__ ((weak, alias("default_fn")));
int module_init(sys_api_t * api)
{
        sysapi = api;
        return appmod_init();
}

int appmod_main(sys_api_t * api) __attribute__ ((weak, alias("default_fn")));
void *appmod_export(void) __attribute__ ((weak, alias("default_fn")));


extern uint32_t _stext;
extern uint32_t _etext;
extern uint32_t _sdata;  /* start address for the .data section */
extern uint32_t _edata;  /* end address for the .data section */
extern uint32_t _sbss;       /* start address for the .bss section */
extern uint32_t _ebss;       /* end address for the .bss section */

static module_t appmod _module_header_entry = {
        .magic_num = MODULE_MAGIC,
        .text_start = (uint32_t)&_stext,
        .text_end = (uint32_t)&_etext,
        .data_start = (uint32_t)&_sdata,
        .data_end = (uint32_t)&_edata,
        .bss_start = (uint32_t)&_sbss,
        .bss_end = (uint32_t)&_ebss,
        .module_init = module_init,
        .module_main = appmod_main,
        .module_export = appmod_export,
};
